package cn.wky.cale.calculate.parser;

import android.util.Log;

import cn.wky.cale.calculate.lex.Lexer;
import cn.wky.cale.calculate.lex.Lexer.TokenType;
import cn.wky.cale.calculate.lex.Lexer.TokenEnum;

public class Parser {
    private TokenType tokenType;
    private Lexer lexer;

    public static class ParserException extends Exception {
        public ParserException(String message) {
            super(message);
        }
    }

    public Parser(Lexer lexer) {
        this.lexer = lexer;
    }

    private TokenType getTokenType() {
        if (tokenType != null) {
            TokenType temp = tokenType;
            tokenType = null;
            Log.d("token", temp.toString());
            return temp;
        } else {
            TokenType temp = lexer.getToken();
            if (temp == null) return null;
            Log.d("token", temp.toString());
            return temp;
        }
    }

    private void back(TokenType tokenType) {
        this.tokenType = tokenType;
    }

    public double expression() throws ParserException {
        double left = term();
        while (true) {
            TokenType token = getTokenType();
            if (token == null) break;
            if (token.tokenEnum == TokenEnum.ADD || token.tokenEnum == TokenEnum.SUB) {
                double right = term();
                if (token.tokenEnum == TokenEnum.ADD) {
                    left = left + right;
                } else {
                    left = left - right;
                }
            } else {
                back(token);
                break;
            }
        }
        return left;
    }

    private double term() throws ParserException {
        double left = factor();
        while (true) {
            TokenType token = getTokenType();
            if (token == null) break;
            if (token.tokenEnum == TokenEnum.MUL || token.tokenEnum == TokenEnum.DIV) {
                double right = term();
                if (token.tokenEnum == TokenEnum.MUL) {
                    left = left * right;
                } else {
                    left = left / right;
                }
            } else {
                back(token);
                break;
            }
        }
        return left;
    }

    private double factor() throws ParserException {
        TokenType token = getTokenType();
        if (token == null) return 0;
        if (token.tokenEnum == TokenEnum.NUM) {
            return token.value;
        } else {
            throw new ParserException("数字解析错误");
        }
    }
}
